#include "BridgeTool.h"
#include "GeeJoan.h"
#include "innertype.h"
const std::string HexCode = "0123456789ABCDEF";
#include <iostream>
#include <chrono>
std::string HexToString(const std::string &data)
{
    std::string result;
    for (int i = 0; i < data.length(); i += 2)
    {
        std::string byte = data.substr(i, 2);
        char chr = (char) strtol(byte.c_str(), NULL, 16);
        result.push_back(chr);
    }
    return result;
}


std::string StringToHex(const std::string &data)
{

    std::string result ;
    uint8_t currTemp = 0;
    for (int i = 0; i < data.size();  ++i )
    {
        currTemp = data[i] & 0xff;
        result.push_back(HexCode[currTemp>>4]);
        result.push_back(HexCode[currTemp&0x0f]);
    }
    return result;
}


int64_t getTimeMicro()
{
    std::chrono::time_point<std::chrono::system_clock> p = std::chrono::system_clock::now();
    return std::chrono::duration_cast<std::chrono::microseconds>( p.time_since_epoch()).count();
}


int64_t getTimeMilli()
{
    return getTimeMicro() / 1000;
}
static int taskid_ = 1;
BridgeTool::BridgeTool(QObject *parent) : QObject(parent)
{

}

static int networkPackckage(char* body , int bodylen , int mod , int type_sub , std::string &output)
{
    char *buffer = 0 ;
    char* keypari = "";
    int len = serialzeNetWorkPackageRequest((void**)&buffer,(NetWorkPackageModel) mod, type_sub,
                                            taskid_++, body, bodylen, keypari, 0);
    output= std::string(buffer , len);

    if(buffer){
        free( buffer ); // 释放内存
    }
    if (len > 0 )
    {
        return 0;
    }else {
        return -1;
    }
}



typedef   std::function<int(int code , int64_t taskid , int type_m , int type_sub , void *body , int bodylen)> SubtypeEvent;



static int networkPackckageRespBase(char* body , int bodylen ,SubtypeEvent subtypeEvent)
{
    char *buffer = 0 ;
    char* keypari = "";
    //    GeeJoan__Protocol__NetWork__NetWorkPackageRespose **out, void *buffer, int bufferLen

    NetWorkPackageRespose *resp = 0 ;
    // 解包
    ERRORCODE errcode = deserialzeNetWorkPackageRespose(&resp ,body ,bodylen );
    int ret = 0 ;
    if (errcode== ERRORCODE::ERROR_OK)
    {

        ret =  subtypeEvent(resp->code , resp->taskid , resp->type_m , resp->type_sub , resp->body.data , resp->body.len);

    }else
    {
        // 解包失败
        ret =  -1;
    }
    free_NetWorkPackageRespose(resp);

    return  ret ;
}




void loginEvent(void *data , int datalen , NoticeCallbackFunction cb , void *userdata);

void registerEvent(int code , NoticeCallbackFunction cb , void *userdata);

static int BusinessDepack(char* body , int bodylen ,NoticeCallbackFunction cb ,void *userdata){
    int localNetworkPackckageRespBase = networkPackckageRespBase(
                body , bodylen ,
                [&](int code , int64_t taskid , int type_m , int type_sub , void *body , int bodylen){
        //　一级过滤

        if(code != 200)
        {
            LOGLISTERNER()<<"NetworkPackckageResp , code = "<< code <<" type_m = "<<type_m <<" type_sub = " <<type_sub;
            return -1;
        }

        // 业务分发
        //目前右目标的路由


        if (type_m == 1 && type_sub == AUTH_REGISTER )
        {
            registerEvent(code , cb ,userdata);
        }
        if(type_m == 1 && type_sub ==AUTH_LOGIN )
        {
            loginEvent(body , bodylen , cb ,userdata );
        }


        return 0;
    });

    return localNetworkPackckageRespBase;
}

void loginEvent(void *data , int datalen , NoticeCallbackFunction cb , void *userdata)
{
    LoginRespose *resp = 0 ;
    ERRORCODE errcode = deserialzeLoginRespose(&resp , data , datalen ) ;

    if(errcode == ERROR_OK)
    {
        LOGCALLBACK()<< " your Token = " << resp->token ;
        cb("LoginEvent" , "登录成功！" , userdata);
    }else
    {
        cb("LoginEvent" , "登录失败！" , userdata);
    }
    free_LoginRespose(resp);
    return;
}
void registerEvent(int code , NoticeCallbackFunction cb , void *userdata)
{
    //API 没有相应

    cb("RegisterEvent" , "注册成功!",userdata);
    return;

}

QString BridgeTool::loginNetWorkPack(QString username, QString password)
{
    char *loginBuffer = 0; //储存序列化后的数据包 buff
    int64_t currentTime = getTimeMilli();
    //  & 才能修改为指针的buff
    int loginLen = serialzeLoginRequest((void**)&loginBuffer , username.toStdString().c_str() ,  password.toStdString().c_str(), currentTime);

    if (loginLen < 0 )
    {
        fprintf(stderr , "serial Login Request Error \r\n");
        return "";
    } else
    {
        printf("serial Login Request Success \r\n");
    }

    std::string output;

    int ret = networkPackckage(loginBuffer , loginLen , NetWorkPackageModel_AuthMod , AUTH_LOGIN, output);

    if (ret < 0 )
    {
        fprintf(stderr , "serial Login Request Error \r\n");
        return  "";
    }
    QString retStr =QString("%1").arg(StringToHex(output).c_str());

    if(loginBuffer)
    {
        free(loginBuffer);
    }

    return retStr;
}

QString BridgeTool::registerNetWorkPack(QString username, QString password, QString email)
{
    char *buffer = 0; //储存序列化后的数据包 buff
    int64_t currentTime = getTimeMilli();
    //  & 才能修改为指针的buff
    int tempLen = serialzeRegisterAPI((void**)&buffer , username.toStdString().c_str() ,  password.toStdString().c_str(), email.toStdString().c_str());

    if (tempLen < 0 )
    {
        fprintf(stderr , "serial Register Api Error \r\n");
        return "";
    } else
    {
        printf("serial Register Api Success \r\n");
    }

    std::string output;

    int ret = networkPackckage(buffer , tempLen , NetWorkPackageModel_AuthMod , AUTH_REGISTER, output);

    if (ret < 0 )
    {
        fprintf(stderr , "serial Login Request Error \r\n");
        return  "";
    }
    QString retStr =QString("%1").arg(StringToHex(output).c_str());

    if(buffer)
    {
        free(buffer);
    }

    return retStr;
}

QString BridgeTool::loginDeviceNetWorkPack(QString deviceToken)
{
    char *buffer = 0; //储存序列化后的数据包 buff
    int64_t currentTime = getTimeMilli();
    //  & 才能修改为指针的buff
    int tempLen=serialzeLoginDeviceAPI((void**)&buffer , deviceToken.toStdString().c_str() , (long long )currentTime);
    if (tempLen < 0 )
    {
        fprintf(stderr , "serial Register Api Error \r\n");
        return "";
    } else
    {
        printf("serial Register Api Success \r\n");
    }

    std::string output;

    int ret = networkPackckage(buffer , tempLen , NetWorkPackageModel_AuthMod , AUTH_REGISTER, output);

    if (ret < 0 )
    {
        fprintf(stderr , "serial Login Request Error \r\n");
        return  "";
    }
    QString retStr =QString("%1").arg(StringToHex(output).c_str());

    if(buffer)
    {
        free(buffer);
    }

    return retStr;
}
int BridgeTool::TcpRecvCallback(std::string& recvMessage, NoticeCallbackFunction cb , void *userdata)
{

    qDebug()<<" buffer = " << StringToHex(recvMessage).c_str();
    return BusinessDepack((char*)recvMessage.c_str() , recvMessage.length() , cb , userdata);
}
